

package com.xz.auth.controller;
import com.xz.auth.service.AuthorizationService;
import com.xz.common.result.Result;
import com.xz.common.result.ResultCodeEnum;
import com.xz.common.utils.JwtUtils;
import com.xz.common.utils.RedisUtils;
import com.xz.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;

@RestController
@CrossOrigin
public class AccountController {

    @Autowired
    AuthorizationService authorizationService;

    @Autowired
    RedisUtils redisUtils;


    @PostMapping("/login")
    public Result<?> login(@RequestBody User user){

        if(user.getUsername().equals("admin")&&user.getPassword().equals("123456")){
            //登录成功
            //创建token
            String accessToken = authorizationService.createAccessIdToken(user.getUsername());
            String refreshToken = authorizationService.createRefreshIdToken(user.getUsername());
            if(accessToken == null || refreshToken == null){
                return Result.fail("failed");
            }

            //id_refreshTokenStartTime---标识刷新令牌开始时间
            //缓存当前登录用户 refreshToken 创建的起始时间，这个会在刷新accessToken方法中 判断是否要重新生成(刷新)refreshToken时用到
            redisUtils.set("id_refreshTokenStartTime"+user.getUsername(),String.valueOf(System.currentTimeMillis()) ,3*60);

            //更新用户最近登录时间
            // user.setLastLoginTime(new Date().toLocaleString());
            //更新user到数据库成功后缓存(数据库操作这里就忽略了)
            HashMap<String,Object> res = new HashMap<String,Object>();
            //response
            res.put("accessToken",accessToken);
            res.put("refreshToken",refreshToken);
            return Result.ok(res);
        }

        return Result.fail("failed");
    }

    /**
     * 用 refreshToken 来刷新 accessToken
     * @param refreshToken refreshToken
     * @return
     */
    @GetMapping("/accessToken/refresh/{refreshToken}")
    public Result<?> accessTokenRefresh(@PathVariable("refreshToken") String refreshToken){
        //刷新accessToken:生成新的accessToken
        boolean cheackToken = JwtUtils.checkToken(refreshToken);
        System.out.println("刷新的token"+refreshToken);
        if(!cheackToken){
            //通过返回码 告诉客户端 refreshToken过期了，需要客户端就得跳转登录界面
            return Result.build(ResultCodeEnum.TOKEN_FAIL.getCode(),ResultCodeEnum.TOKEN_FAIL.getMessage());
        }
        String account = JwtUtils.getUsernameByToken(refreshToken);
        //创建新的accessToken
        String accessToken = authorizationService.createAccessIdToken(account);

        //minTimeOfRefreshToken  最短刷新时间
        //refreshTokenStartTime  刷新令牌开始时间

        //下面判断是否刷新 refreshToken，如果refreshToken 快过期了 需要重新生成一个替换掉
        long minTimeOfRefreshToken = 2*AuthorizationService.accessTokenExpirationTime;//refreshToken 有效时长是应该为accessToken有效时长的2倍 (我在博文里有介绍)
        Long refreshTokenStartTime = Long.valueOf(redisUtils.get("id_refreshTokenStartTime"+account));//refreshToken创建的起始时间点

        //(refreshToken上次创建的时间点 + refreshToken的有效时长 - 当前时间点) 表示refreshToken还剩余的有效时长，如果小于2倍accessToken时长 ，则刷新 refreshToken
        if(refreshTokenStartTime == null || (refreshTokenStartTime + AuthorizationService.refreshTokenExpirationTime) - System.currentTimeMillis() <= minTimeOfRefreshToken){
            //刷新refreshToken
            refreshToken = authorizationService.createRefreshIdToken(account);
            redisUtils.set("id_refreshTokenStartTime"+account,String.valueOf(System.currentTimeMillis()),3*60);
        }

        HashMap<String,Object> res = new HashMap<String,Object>();
        //response
        res.put("accessToken",accessToken);
        res.put("refreshToken",refreshToken);
        return Result.ok(res);
    }



    @GetMapping("/user/{accessToken}")
    public Result<?> userInfo(@PathVariable("accessToken") String accessToken){

        boolean cheackToken = JwtUtils.checkToken(accessToken);

        if(!cheackToken){
            //通过返回码 告诉客户端 accessToken过期了，需要调用刷新accessToken的接口
            return Result.build(ResultCodeEnum.TOKEN_EXIST.getCode(),ResultCodeEnum.TOKEN_EXIST.getMessage());
        }
        String account = JwtUtils.getUsernameByToken(accessToken);
        System.out.println("account="+account);
        //response

        return Result.ok("success");
    }

}
